Skip to content

WIP: OBLS-837 Add discrete picking order list screen - #430

Merged
awalkowiak merged 12 commits into
developfrom
OBLS-837
Jul 29, 2026
Merged

WIP: OBLS-837 Add discrete picking order list screen#430
awalkowiak merged 12 commits into
developfrom
OBLS-837

Conversation

@jmiranda

Copy link
Copy Markdown
Member

Summary

Adds a new Discrete Picking entry to the Dashboard that lists all open orders ready for picking across every queue type, with real-time search and queue-type filter chips. Tapping an order seeds the picking session and reuses the existing Pick Location → … → Staging flow, one order at a time. This is the "one order at a time" counterpart to the existing batch Picking flow.

Implements OBLS-837.

Changes

Feature

  • Data layergetPickTasksApi now runs unfiltered (params optional); added getOpenPickTasksApi to fetch all open (PENDING/PICKING) pick tasks across all queue types, plus getOpenPickTasksAction action/saga/watcher.
  • Types — new DiscretePickingOrder view model.
  • HandoffPickingContext.startOrderSession(requisitionId) seeds a single-order session via the existing getPickTasksByRequisitionAction, then navigation continues into the existing Pick Location flow.
  • UI (src/screens/Picking/) — DiscretePickingListScreen, DiscretePickingOrderCard, DiscretePickingCardSkeleton, discretePickingStyles, and discretePickingLib (group-by-requisition, priority sort, real-time filter, chip counts). Reuses BarcodeSearchHeader, ListLoadingSkeleton, EmptyView, emptyStateMessage.
  • Wiring — route in Main.tsx; entry in dashboardData.ts.

CI / preview

  • Enabled the previously-disabled pull_request_target_branch: develop trigger so PRs build an APK and deploy to Appetize for preview.
  • Pointed appetize-deploy at a stable shared preview app via $APPETIZE_PUBLIC_KEY (falls back to creating a new app per build when unset).

Notes / follow-ups

  • The multi-field filter panel (Destination / Queue Type / Assignee / Status) from the ticket's acceptance criteria is intentionally deferred — the mockup annotates it as a future enhancement. This PR ships the list, search, queue chips, sort, and empty state.
  • Backend dependency: the list relies on the pick-tasks endpoint returning all open tasks when deliveryTypeCode/ordersCount are omitted (filtered here to status=PENDING&status=PICKING). Confirm this behavior on the backend.
  • The shared downstream flow currently routes back through PickingPickType/staging on completion; adjusting the return destination for discrete picks is a possible follow-up.

Testing

  • yarn lint clean; app-level tsc clean (remaining tsc errors are pre-existing @react-navigation lib-def parse issues under node_modules, unrelated to this change).
  • Manual: Dashboard → Discrete Picking → list loads open orders sorted by priority; search filters in real time across order #, customer, and product; queue chips filter (All clears); empty state renders; tapping an order lands on Pick Location and completes the existing flow.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 8 commits July 24, 2026 02:50
Add a new "Discrete Picking" Dashboard entry that lists all open orders
ready for picking across every queue type, with real-time search and
queue-type filter chips. Tapping an order seeds the picking session and
reuses the existing Pick Location flow, one order at a time.

- apis/picking: allow getPickTasksApi to run unfiltered; add
  getOpenPickTasksApi for all open (PENDING/PICKING) tasks
- redux: add getOpenPickTasksAction + saga + watcher
- types: add DiscretePickingOrder view model
- PickingContext: add startOrderSession(requisitionId) to seed a
  single-order session via getPickTasksByRequisitionAction
- screens/Picking: add DiscretePickingListScreen, order card, skeleton,
  styles, and grouping/sort/filter helpers
- wire route in Main and add Dashboard entry

The multi-field filter panel (Destination/Queue Type/Assignee/Status) is
intentionally deferred to a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
Build an APK and deploy it to Appetize for every pull request targeting
develop, so reviewers can preview changes in the browser.

- Enable the pull_request_target_branch: develop trigger (was disabled),
  routing PR builds through the existing android-only workflow
- Point appetize-deploy at a stable shared preview app via APPETIZE_APP_ID
  so the preview URL stays constant across builds (falls back to creating
  a new app per build when the var is unset)

Requires (Bitrise dashboard, one-time): enable Pull Request builds for the
app, and set APPETIZE_APP_ID to a preview app's public key.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
The appetize-deploy step's input is public_key, not app_id; the previous
key was ignored, so every build created a new Appetize app. Use
public_key: $APPETIZE_PUBLIC_KEY so builds update one stable preview app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
Remove the public_key input added earlier. With APPETIZE_PUBLIC_KEY unset
it resolved to empty, and this appetize-deploy version may mishandle an
empty public_key. Match the proven develop config (no public_key input),
which creates a new preview app per build. The stable shared-app key can
be reintroduced once the pipeline is green and a key exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
PR builds now deploy to a dedicated PR preview Appetize app instead of
overwriting the main app used by develop. A script selects the target
public key by build type ($BITRISE_PULL_REQUEST distinguishes PR from
push builds) and appetize-deploy uses it. A run_if guard skips the deploy
entirely when no key is configured, so it never falls back to creating a
new app.

Requires two Bitrise env vars: APPETIZE_DEVELOP_PUBLIC_KEY (main app) and
APPETIZE_PR_PUBLIC_KEY (PR preview app).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
Set APPETIZE_DEVELOP_PUBLIC_KEY to the main app used by develop. Leave
APPETIZE_PR_PUBLIC_KEY empty until the PR preview app is created; the
appetize-deploy run_if guard skips the deploy while it is empty, so PR
builds cannot overwrite the main app in the meantime.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
The select-app script runs under set -u, so referencing an unset
APPETIZE_*_PUBLIC_KEY aborted the step (as happened before the keys were
defined, and would recur if Bitrise omits an empty-valued env var). Use
${VAR:-} defaults so the script tolerates unset or empty keys; the
run_if guard on appetize-deploy still skips the deploy when the resolved
key is empty.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
On PR builds only, append "(Experimental)" to the Android app_name after
branding runs, so the PR preview app is clearly distinguishable from the
stable build in Appetize (which shows the app name from the APK manifest).
Guarded by BITRISE_PULL_REQUEST so stable/develop builds keep the plain
name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
claude added 3 commits July 24, 2026 18:48
Appetize keys apps by applicationId, so a same-package PR APK merged into
the stable app instead of creating a separate one. On PR builds, suffix
the applicationId with .experimental (alongside the app-name tag) so the
PR build uploads as its own Appetize app with its own URL. No package-tied
services (Firebase/Maps/google-services) exist, so the suffix is safe.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
Set APPETIZE_PR_PUBLIC_KEY to the PR preview app's key so PR builds now
deploy the experimental APK to their own Appetize app instead of skipping
the deploy. For the v1 API the appetize-deploy step uses, the build id and
public key are interchangeable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
After deploying, POST a note to the Appetize v1 API for the deployed app
with PR number, branch, short commit, and build number, so each preview
is self-documenting in the dashboard. The appetize-deploy step can't set
notes itself. The v1 API has no tags field, so tags stay manual. The call
is non-fatal so a note failure never reds the build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
@jmiranda
jmiranda marked this pull request as draft July 27, 2026 18:27
@jmiranda jmiranda changed the title OBLS-837 Add discrete picking order list screen WIP: OBLS-837 Add discrete picking order list screen Jul 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Discrete Picking” dashboard entry and screen that lists open pickable orders (grouped from open pick tasks) and starts a single-order picking session that reuses the existing Pick Location → … → Staging flow. Also updates the picking API layer/sagas to support fetching open tasks across all queue types and adjusts Bitrise to build/deploy PR previews to Appetize.

Changes:

  • Introduces Discrete Picking list UI (cards, skeleton/loading, search + queue-type chips) and wires it into navigation + dashboard.
  • Adds data-layer support for “open pick tasks” (API + Redux action/saga/watcher) and a DiscretePickingOrder view model with grouping/sorting/filtering helpers.
  • Updates Bitrise PR triggers and Appetize deploy behavior (shared preview keys + PR build annotation).

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/types/picking.ts Adds DiscretePickingOrder view model for the discrete picking list.
src/screens/Picking/PickingContext.tsx Adds startOrderSession(requisitionId) to seed a single-order picking session.
src/screens/Picking/discretePickingStyles.ts New styles for discrete picking list/cards/chips.
src/screens/Picking/DiscretePickingOrderCard.tsx New order card component for discrete picking list.
src/screens/Picking/DiscretePickingListScreen.tsx New discrete picking list screen (fetch, search, queue chips, navigation into picking flow).
src/screens/Picking/discretePickingLib.ts Groups tasks into orders; sorts and filters; computes chip counts.
src/screens/Picking/DiscretePickingCardSkeleton.tsx Loading skeleton card for the list.
src/screens/Dashboard/dashboardData.ts Adds “Discrete Picking” dashboard entry.
src/redux/sagas/picking.ts Adds saga + watcher for fetching open pick tasks.
src/redux/actions/picking.ts Adds GET_OPEN_PICK_TASKS action trio + action creator.
src/Main.tsx Adds route for DiscretePickingList.
src/apis/picking.ts Makes pick-tasks query params optional; adds getOpenPickTasksApi (status=PENDING/PICKING).
.bitrise/bitrise.yml Enables PR-to-develop builds + Appetize deploy targeting/annotation + PR “experimental” package/name tweak.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +106 to +113
getPickTasksByRequisitionAction(requisitionId, (res) => {
if ('errorMessage' in res || !res.response?.data) {
Alert.alert('Error', 'Failed to load pick tasks for the selected order.');
resolve(false);
return;
}

const orderTasks = res.response.data;
Comment thread .bitrise/bitrise.yml Outdated
else
NOTE="${BITRISE_GIT_BRANCH:-} - ${SHA} - build ${BITRISE_BUILD_NUMBER:-}"
fi
BODY="$(jq -n --arg note "$NOTE" '{note: $note}')"
- startOrderSession: surface the callback's errorMessage in the alert
  (consistent with startSession) instead of a generic message, so
  network/auth/backend failures are distinguishable.
- Appetize note step: build the JSON body with printf/sed instead of jq,
  so the step is self-contained and doesn't fail if the skippable jq
  brew-install was skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011zmhJ6yv58QsHzj8EwAnZb
Comment thread .bitrise/bitrise.yml
# applicationId, so the suffix makes the PR build a separate Appetize app
# (its own URL) instead of overwriting the stable app. Runs after branding
# (which sets app_name) and before the release assemble.
- script@1:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be a part of bundle::release-steps-android: {} or the bundle::setup-steps-android: {}

Comment thread .bitrise/bitrise.yml
# Build a preview (APK + Appetize deploy) for every pull request into develop.
- pull_request_target_branch: develop
enabled: false
workflow: android-only

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will now trigger a build on each PR to the develop branch. Do we want to have it? I think I'd prefer to have a different approach here. I'd make a preview build when the code is pushed to the preview/* branch (or something like that). Not everything (eg a commit with a typo fix after review) needs a publish to Appetize and to be sent out to Bitrise build recipients. Plus, not that long ago we ran into a credits limit due to building on each PR to develop.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

src/screens/Picking/PickingContext.tsx:114

  • startOrderSession doesn't handle the API's { errorCode, message } error shape (used elsewhere in the picking flow). If the requisition fetch returns errorCode without throwing, this will currently fall through and may show a generic error or attempt to use an undefined task list.
        getPickTasksByRequisitionAction(requisitionId, (res) => {
          if (res.errorMessage || !res.response?.data) {
            Alert.alert('Error', res.errorMessage ?? 'Failed to load pick tasks for the selected order.');
            resolve(false);
            return;
          }

          const orderTasks = res.response.data;

src/screens/Picking/DiscretePickingListScreen.tsx:47

  • The open-order fetch callback ignores backend { errorCode, message } responses (which this codebase uses elsewhere in picking). If the endpoint returns errorCode with a 200, this screen will silently show an empty state instead of reporting the failure.
      getOpenPickTasksAction(({ response, errorMessage }) => {
        if (!errorMessage && response?.data) {
          setTasks(response.data);
        }
        setIsRefreshing(false);
        setHasLoaded(true);
      })

src/screens/Picking/DiscretePickingListScreen.tsx:3

  • fetchOrders should surface API failures to the user (this file currently doesn't import Alert, so there’s no way to show the error inline like other picking screens do). Adding Alert enables consistent error handling in the fetch callback below.

This issue also appears on line 41 of the same file.

import { FlatList, ScrollView, View } from 'react-native';

@awalkowiak
awalkowiak marked this pull request as ready for review July 29, 2026 15:56

@awalkowiak awalkowiak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am merging as is so we can QA this tomorrow. The bitrise comments will be addressed separately if needed

@awalkowiak
awalkowiak merged commit 6cb1c49 into develop Jul 29, 2026
2 checks passed
@awalkowiak
awalkowiak deleted the OBLS-837 branch July 29, 2026 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants